package com.by.rpc.netty;

import com.by.log.Logger;
import com.by.log.LoggerFactory;
import com.by.log.TraceContext;
import com.by.rpc.dto.RpcRequest;
import com.by.rpc.dto.RpcResponse;
import com.by.rpc.exception.BusinessException;
import com.by.rpc.provider.ServiceProvider;
import com.by.rpc.util.ServiceParameter;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.List;

/**
 * Netty服务端处理器，用于处理RPC请求
 */
public class RpcServerHandler extends SimpleChannelInboundHandler<RpcRequest> {
    private static final Logger log = LoggerFactory.getLogger(RpcServerHandler.class);
    private final ServiceProvider serviceProvider;
    
    public RpcServerHandler(ServiceProvider serviceProvider) {
        this.serviceProvider = serviceProvider;
    }

    @Override
    protected void channelRead0(ChannelHandlerContext ctx, RpcRequest rpcRequest) throws Exception {
        // 设置追踪上下文
        if (rpcRequest.getTraceId() != null) {
            TraceContext traceContext = TraceContext.getCurrentContext();
            traceContext.setTraceId(rpcRequest.getTraceId());
            traceContext.setSpanId(rpcRequest.getSpanId());
            traceContext.setParentSpanId(rpcRequest.getParentSpanId());
        }
        
        log.info("Received RPC request: {}", rpcRequest);

        RpcResponse rpcResponse = new RpcResponse();
        rpcResponse.setRequestId(rpcRequest.getRequestId());
        // 设置追踪信息到响应中
        rpcResponse.setTraceId(rpcRequest.getTraceId());
        rpcResponse.setSpanId(rpcRequest.getSpanId());
        rpcResponse.setParentSpanId(rpcRequest.getParentSpanId());

        Object result = null;
        try {
            // 以下逻辑不变（服务查找、方法调用等）
            Object service = null;
            if (rpcRequest.getInterfaceName() != null && !rpcRequest.getInterfaceName().isEmpty()) {
                service = serviceProvider.getLoadedInterface(rpcRequest.getInterfaceName(), rpcRequest.getVersion(), rpcRequest.getGroup());
            } else {
                service = serviceProvider.getLoadedService(
                        rpcRequest.getServiceName(),
                        rpcRequest.getVersion(),
                        rpcRequest.getGroup()
                );
            }

            if (service == null) {
                throw new RuntimeException(String.format("Service %s:%s:%s not found",
                        rpcRequest.getServiceName(), rpcRequest.getVersion(), rpcRequest.getGroup()));
            }
            // 处理参数类型和参数值
            Class<?>[] parameterTypes = new Class[0];
            Object[] parameters = new Object[0];

            List<ServiceParameter> serviceParameters = rpcRequest.getParameters();
            if (serviceParameters != null && !serviceParameters.isEmpty()) {
                parameterTypes = new Class[serviceParameters.size()];
                parameters = new Object[serviceParameters.size()];

                for (int i = 0; i < serviceParameters.size(); i++) {
                    ServiceParameter param = serviceParameters.get(i);
                    // 获取参数类型
                    String typeName = param.getType();
                    Class<?> paramType = getClassForName(typeName);
                    parameterTypes[i] = paramType;

                    // 获取参数值并进行类型转换
                    Object paramValue = param.getValue();
                    parameters[i] = convertParameterValue(paramValue, paramType);
                }
            }

            // 查找匹配的方法，解决基本类型和包装类型不匹配问题
            Method method = findMatchingMethod(service.getClass(), rpcRequest.getMethodName(), parameterTypes);

            // 调用目标方法
            result = method.invoke(service, parameters);

            // Set successful response
            rpcResponse.setStatus(RpcResponse.ResponseStatus.SUCCESS);
            rpcResponse.setData(result);
        } catch (InvocationTargetException e) {
            // 处理业务异常
            Throwable targetException = e.getTargetException();
            rpcResponse.setStatus(RpcResponse.ResponseStatus.FAIL);
            
            if (targetException instanceof BusinessException) {
                BusinessException businessException = (BusinessException) targetException;
                rpcResponse.setErrorMsg(businessException.getMessage());
                rpcResponse.setErrorCode(businessException.getCode());
            } else {
                rpcResponse.setErrorMsg(targetException.getMessage());
                rpcResponse.setErrorCode(500); // 默认技术异常码
            }
            log.error("RPC request processing failed", targetException);
        } catch (Exception e) {
            // Set failed response
            rpcResponse.setStatus(RpcResponse.ResponseStatus.FAIL);
            rpcResponse.setErrorMsg(e.getMessage());
            rpcResponse.setErrorCode(500); // 默认技术异常码
            log.error("RPC request processing failed", e);
        } catch (Throwable t) {
            // 捕获所有可能的错误，确保任何情况下都有响应返回给客户端
            rpcResponse.setStatus(RpcResponse.ResponseStatus.FAIL);
            rpcResponse.setErrorMsg("系统内部错误: " + t.getMessage());
            rpcResponse.setErrorCode(500);
            log.error("Unexpected error during RPC request processing", t);
        }

        // Send response back to client
        ctx.writeAndFlush(rpcResponse);
    }

    /**
     * 查找匹配的方法，解决基本类型和包装类型不匹配问题
     *
     * @param clazz          服务类
     * @param methodName     方法名
     * @param parameterTypes 参数类型数组
     * @return 匹配的方法
     * @throws NoSuchMethodException 当找不到匹配方法时抛出异常
     */
    private Method findMatchingMethod(Class<?> clazz, String methodName, Class<?>[] parameterTypes) throws NoSuchMethodException {
        // 首先尝试直接查找精确匹配的方法
        try {
            return clazz.getMethod(methodName, parameterTypes);
        } catch (NoSuchMethodException e) {
            // 如果直接查找失败，则尝试查找兼容的方法
            Method[] methods = clazz.getMethods();
            for (Method method : methods) {
                if (method.getName().equals(methodName) && isParameterTypesCompatible(method.getParameterTypes(), parameterTypes)) {
                    return method;
                }
            }
            // 如果仍然找不到匹配的方法，则抛出异常
            throw new NoSuchMethodException("No matching method found: " + methodName + " with parameters " + java.util.Arrays.toString(parameterTypes));
        }
    }

    /**
     * 检查参数类型是否兼容（解决基本类型和包装类型的匹配问题）
     *
     * @param methodParamTypes  方法声明的参数类型
     * @param requestParamTypes 请求中的参数类型
     * @return 是否兼容
     */
    private boolean isParameterTypesCompatible(Class<?>[] methodParamTypes, Class<?>[] requestParamTypes) {
        if (methodParamTypes.length != requestParamTypes.length) {
            return false;
        }

        for (int i = 0; i < methodParamTypes.length; i++) {
            Class<?> methodType = methodParamTypes[i];
            Class<?> requestType = requestParamTypes[i];

            // 类型完全匹配
            if (methodType == requestType) {
                continue;
            }

            // 处理基本类型和包装类型的兼容性
            if (isPrimitiveAndWrapperCompatible(methodType, requestType)) {
                continue;
            }

            // 处理继承关系
            if (methodType.isAssignableFrom(requestType)) {
                continue;
            }

            // 类型不兼容
            return false;
        }

        return true;
    }

    /**
     * 检查基本类型和包装类型是否兼容
     *
     * @param type1 类型1
     * @param type2 类型2
     * @return 是否兼容
     */
    private boolean isPrimitiveAndWrapperCompatible(Class<?> type1, Class<?> type2) {
        if (type1.isPrimitive()) {
            return getWrapperClass(type1) == type2;
        } else if (type2.isPrimitive()) {
            return getWrapperClass(type2) == type1;
        }
        return false;
    }

    /**
     * 获取基本类型的包装类
     *
     * @param primitiveType 基本类型
     * @return 对应的包装类
     */
    private Class<?> getWrapperClass(Class<?> primitiveType) {
        if (primitiveType == byte.class) return Byte.class;
        if (primitiveType == short.class) return Short.class;
        if (primitiveType == int.class) return Integer.class;
        if (primitiveType == long.class) return Long.class;
        if (primitiveType == float.class) return Float.class;
        if (primitiveType == double.class) return Double.class;
        if (primitiveType == boolean.class) return Boolean.class;
        if (primitiveType == char.class) return Character.class;
        if (primitiveType == void.class) return Void.class;
        return primitiveType;
    }

    /**
     * 根据类名获取Class对象
     *
     * @param typeName 类名
     * @return Class对象
     * @throws ClassNotFoundException 当找不到类时抛出异常
     */
    private Class<?> getClassForName(String typeName) throws ClassNotFoundException {
        // 处理基本数据类型
        switch (typeName) {
            case "byte":
                return byte.class;
            case "short":
                return short.class;
            case "int":
                return int.class;
            case "long":
                return long.class;
            case "float":
                return float.class;
            case "double":
                return double.class;
            case "boolean":
                return boolean.class;
            case "char":
                return char.class;
            case "void":
                return void.class;
            default:
                // 处理数组类型和普通类
                if (typeName.endsWith("[]")) {
                    String componentTypeName = typeName.substring(0, typeName.length() - 2);
                    Class<?> componentType = getClassForName(componentTypeName);
                    return java.lang.reflect.Array.newInstance(componentType, 0).getClass();
                }
                return Class.forName(typeName);
        }
    }

    /**
     * 转换参数值到目标类型
     *
     * @param value      原始参数值
     * @param targetType 目标类型
     * @return 转换后的参数值
     */
    private Object convertParameterValue(Object value, Class<?> targetType) {
        if (value == null) {
            return null;
        }

        // 如果类型已经匹配，直接返回
        if (targetType.isInstance(value)) {
            return value;
        }

        try {
            // 处理基本类型和包装类型
            if (targetType == byte.class || targetType == Byte.class) {
                if (value instanceof Number) {
                    return ((Number) value).byteValue();
                }
                return Byte.parseByte(value.toString());
            } else if (targetType == short.class || targetType == Short.class) {
                if (value instanceof Number) {
                    return ((Number) value).shortValue();
                }
                return Short.parseShort(value.toString());
            } else if (targetType == int.class || targetType == Integer.class) {
                if (value instanceof Number) {
                    return ((Number) value).intValue();
                }
                return Integer.parseInt(value.toString());
            } else if (targetType == long.class || targetType == Long.class) {
                if (value instanceof Number) {
                    return ((Number) value).longValue();
                }
                return Long.parseLong(value.toString());
            } else if (targetType == float.class || targetType == Float.class) {
                if (value instanceof Number) {
                    return ((Number) value).floatValue();
                }
                return Float.parseFloat(value.toString());
            } else if (targetType == double.class || targetType == Double.class) {
                if (value instanceof Number) {
                    return ((Number) value).doubleValue();
                }
                return Double.parseDouble(value.toString());
            } else if (targetType == boolean.class || targetType == Boolean.class) {
                if (value instanceof Boolean) {
                    return value;
                }
                return Boolean.parseBoolean(value.toString());
            } else if (targetType == char.class || targetType == Character.class) {
                String str = value.toString();
                if (str.length() == 1) {
                    return str.charAt(0);
                }
                throw new IllegalArgumentException("Cannot convert string '" + str + "' to char");
            } else if (targetType == String.class) {
                return value.toString();
            } else {
                // Kryo会直接序列化对象，无需JSON转换，仅需确保类型兼容
                if (targetType.isAssignableFrom(value.getClass())) {
                    return value;
                } else {
                    throw new IllegalArgumentException(
                            String.format("Cannot convert %s to %s", value.getClass(), targetType)
                    );
                }
            }
        } catch (Exception e) {
            log.warn("Failed to convert parameter value '{}' to type {}", value, targetType, e);
            return value; // 如果转换失败，返回原始值
        }
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        log.error("RPC server handler exception", cause);
        
        // 发送错误响应给客户端
        RpcResponse errorResponse = new RpcResponse();
        errorResponse.setStatus(RpcResponse.ResponseStatus.FAIL);
        errorResponse.setErrorMsg("服务器内部错误: " + cause.getMessage());
        errorResponse.setErrorCode(500);
        ctx.writeAndFlush(errorResponse);
        ctx.close();
    }
}